package com.zqc.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zqc.common.Const;
import com.zqc.common.R;
import com.zqc.dto.DishDto;
import com.zqc.entity.Category;
import com.zqc.entity.Dish;
import com.zqc.entity.DishFlavor;
import com.zqc.service.CategoryService;
import com.zqc.service.DishFlavorService;
import com.zqc.service.DishService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 菜品管理
 */
@RestController
@RequestMapping("/dish")
@Api(tags = "菜品相关接口")
public class DishController {
    @Autowired
    public DishService dishService;

    @Autowired
    public DishFlavorService dishFlavorService;

    @Autowired
    public CategoryService categoryService;

    @Autowired
    public RedisTemplate<Object, Object> redisTemplate;

    @PostMapping
    @ApiOperation(value = "菜品保存接口")
    public R<String> save(@RequestBody DishDto dishDto) {
        // 保存某个菜品时，需要redis数据同步数据库库，因此，需要清理保存菜品redis中的数据
        String key = "dish_" + dishDto.getCategoryId() + "_1";
        redisTemplate.delete(key);

        dishService.saveDishAndFlavor(dishDto);
        return R.success("菜品添加成功");
    }

    /**
     * 菜品分页查询
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    @ApiOperation(value = "菜品分页查询接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页显示数目", required = true),
            @ApiImplicitParam(name = "name", value = "搜索关键字", required = false)
    })
    public R<Page> page(int page, int pageSize, String name) {
        // 1 创建Page构造器
        Page<Dish> dishPage = new Page<>(page, pageSize);
        Page<DishDto> dishDtoPage = new Page<>();
        dishService.page(dishPage, new LambdaQueryWrapper<Dish>()
                .like(StringUtils.isNotEmpty(name), Dish::getName, name)
                // 查询is_deleted值为 0 ，不删除的商品
                .eq(Dish::getIsDeleted, Const.DISH_NOT_DELETED)
                .orderByAsc(Dish::getSort)
                .orderByDesc(Dish::getUpdateTime)
        );
        // 获取的dishPage里面的dish对象不包含CategoryName，页面不能进行显示，需要经过处理，使用DishDto
        // 对象拷贝
        BeanUtils.copyProperties(dishPage, dishDtoPage, "records");

        List<Dish> records = dishPage.getRecords();
        List<DishDto> dishDtoRecords = records.stream().map(item -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item, dishDto);
            // 获取菜品分类id，查询彩品分类名称
            Long categoryId = item.getCategoryId();
            Category category = categoryService.getById(categoryId);

            if (category != null) {
                dishDto.setCategoryName(category.getName());
            }

            return dishDto;
        }).collect(Collectors.toList());

        // 将处理好的分页数据封装到dishDtoPage里面
        dishDtoPage.setRecords(dishDtoRecords);

        return R.success(dishDtoPage);
    }

    /**
     * 查询单个菜品
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("查询单个菜品详细接口")
    @ApiImplicitParam(name="id",value = "菜品id",required = true)
    public R<DishDto> getById(@PathVariable(name = "id") Long id) {
        DishDto dishDto = dishService.getDishAndFlavors(id);
        return R.success(dishDto);
    }

    @PutMapping
    @ApiOperation("菜品更新接口")
    public R<String> update(@RequestBody DishDto dishDto) {
        // 更新某个菜品时，需要redis数据同步数据库库，因此，需要清理更新菜品redis中的数据
        String key = "dish_" + dishDto.getCategoryId() + "_1";
        redisTemplate.delete(key);

        dishService.updateDishAndFlavors(dishDto);
        return R.success("修改菜品成功");
    }

    /**
     * 批量起售停售
     *
     * @param status
     * @param ids
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("菜品更新状态接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "status",value= "菜品更新状态",required = true),
            @ApiImplicitParam(name = "ids",value = "菜品id数组",required = true)
    })
    public R<String> updateStatus(@PathVariable(name = "status") int status, Long[] ids) {
        dishService.update(new UpdateWrapper<Dish>().in("id", ids).set("status", status));
        return R.success("菜品状态修改成功");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping
    @ApiOperation("删除菜品接口")
    @ApiImplicitParam(name = "ids",value = "菜品id数组")
    public R<String> delete(Long[] ids) {
        dishService.update(new UpdateWrapper<Dish>().in("id", ids).set("is_deleted", Const.DISH_DELETED));
        return R.success("删除商品成功");
    }

    /**
     * 条件查询菜品集合
     *
     * @param dish
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("菜品列表查询接口")
    public R<List<DishDto>> list(Dish dish) {
        List<DishDto> dishDtos = null;
        String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();

        // 先从redis中获取数据
        dishDtos = (List<DishDto>) redisTemplate.opsForValue().get(key);
        // 如果redis中获取到，直接返回
        if (dishDtos != null) {
            return R.success(dishDtos);
        }

        // 没有获取到，在查询数据库，将数据保存到redis中，再返回数据
        List<Dish> dishList = dishService.list(new LambdaQueryWrapper<Dish>()
                // 根据菜品分类查询
                .eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId())
                // 根据菜品起售查
                .eq(Dish::getStatus, Const.SALE_ON)
                .orderByAsc(Dish::getSort)
                .orderByDesc(Dish::getUpdateTime)
        );

        dishDtos = dishList.stream().map(item -> {
            DishDto dishDto = new DishDto();
            // 对象拷贝
            BeanUtils.copyProperties(item, dishDto);

            // 查询category
            Category category = categoryService.getById(item.getCategoryId());
            dishDto.setCategoryName(category.getName());

            // 查询菜品口味集合
            List<DishFlavor> dishFlavors = dishFlavorService.list(
                    new LambdaQueryWrapper<DishFlavor>().eq(DishFlavor::getDishId, item.getId()));
            dishDto.setFlavors(dishFlavors);

            return dishDto;
        }).collect(Collectors.toList());

        // 将数据保存到redis中,缓存一小时
        redisTemplate.opsForValue().set(key, dishDtos, 60, TimeUnit.MINUTES);

        return R.success(dishDtos);
    }
}
